using MeetingManagement.Domain.Common;
using MeetingManagement.Domain.ValueObjects;

namespace MeetingManagement.Domain.Entities
{
    public class Meeting : AggregateRoot
    {
        public string Title { get; private set; }
        public string Description { get; private set; }
        public TimeSlot TimeSlot { get; private set; }
        public string Location { get; private set; }
        public MeetingStatus Status { get; private set; }
        public Guid OrganizerId { get; private set; }
        public Guid? MeetingRoomId { get; private set; }
        public MeetingRoom MeetingRoom { get; private set; }
        public List<Guid> ParticipantIds { get; private set; } = new List<Guid>();
        public List<User> Participants { get; private set; } = new List<User>();
        public string CancellationReason { get; private set; }

        protected Meeting()
        {
            CreatedDate = DateTime.UtcNow;
            UpdatedDate = DateTime.UtcNow;
            Status = MeetingStatus.Scheduled;
        }

        public static Meeting Schedule(string title, string description, DateTime startTime, DateTime endTime,
            string location, Guid organizerId, Guid? meetingRoomId = null)
        {
            if (string.IsNullOrWhiteSpace(title))
                throw new ArgumentException("会议标题不能为空", nameof(title));

            if (startTime >= endTime)
                throw new ArgumentException("会议开始时间必须早于结束时间", nameof(startTime));

            if (startTime < DateTime.Now)
                throw new ArgumentException("不能安排过去的会议", nameof(startTime));

            var meeting = new Meeting
            {
                Title = title,
                Description = description,
                TimeSlot = TimeSlot.Create(startTime, endTime),
                Location = location,
                Status = MeetingStatus.Scheduled,
                OrganizerId = organizerId,
                MeetingRoomId = meetingRoomId
            };

            return meeting;
        }

        public void AddParticipant(Guid participantId)
        {
            if (participantId == Guid.Empty)
                throw new ArgumentException("参与者ID无效", nameof(participantId));

            if (Status == MeetingStatus.Cancelled)
                throw new InvalidOperationException("不能向已取消的会议添加参与者");

            if (!ParticipantIds.Contains(participantId))
            {
                ParticipantIds.Add(participantId);
                UpdatedDate = DateTime.UtcNow;
            }
        }

        public void RemoveParticipant(Guid participantId)
        {
            if (participantId == Guid.Empty)
                throw new ArgumentException("参与者ID无效", nameof(participantId));

            if (Status == MeetingStatus.Cancelled)
                throw new InvalidOperationException("不能从已取消的会议移除参与者");

            if (ParticipantIds.Remove(participantId))
            {
                var participant = Participants.FirstOrDefault(p => p.Id == participantId);
                if (participant != null)
                    Participants.Remove(participant);

                UpdatedDate = DateTime.UtcNow;
            }
        }

        public void Cancel(string reason = null)
        {
            if (Status == MeetingStatus.Cancelled)
                return;

            Status = MeetingStatus.Cancelled;
            CancellationReason = reason;
            UpdatedDate = DateTime.UtcNow;
        }

        public void Reschedule(DateTime newStartTime, DateTime newEndTime)
        {
            if (Status == MeetingStatus.Cancelled)
                throw new InvalidOperationException("不能重新安排已取消的会议");

            if (newStartTime >= newEndTime)
                throw new ArgumentException("会议开始时间必须早于结束时间", nameof(newStartTime));

            if (newStartTime < DateTime.Now)
                throw new ArgumentException("不能安排过去的会议", nameof(newStartTime));

            TimeSlot = TimeSlot.Create(newStartTime, newEndTime);
            UpdatedDate = DateTime.UtcNow;
        }

        public void AssignMeetingRoom(Guid meetingRoomId)
        {
            if (Status == MeetingStatus.Cancelled)
                throw new InvalidOperationException("不能为已取消的会议分配会议室");

            MeetingRoomId = meetingRoomId;
            UpdatedDate = DateTime.UtcNow;
        }

        public DateTime GetStartTime() => TimeSlot.Start;
        public DateTime GetEndTime() => TimeSlot.End;
        public TimeSpan GetDuration() => TimeSlot.Duration;

        public bool OverlapsWith(DateTime start, DateTime end)
        {
            if (Status == MeetingStatus.Cancelled)
                return false;

            return TimeSlot.Start < end && start < TimeSlot.End;
        }

        public void AssignMeetingRoom(MeetingRoom room)
        {
            if (room == null)
                throw new ArgumentNullException(nameof(room));

            if (Status == MeetingStatus.Cancelled)
                throw new InvalidOperationException("不能为已取消的会议分配会议室");

            if (!room.IsActive)
                throw new InvalidOperationException("不能分配非活跃的会议室");

            MeetingRoom = room;
            MeetingRoomId = room.Id;

            if (!room.Meetings.Contains(this))
                room.Meetings.Add(this);

            UpdatedDate = DateTime.UtcNow;
        }

        public void AssignParticipant(User user)
        {
            if (user == null)
                throw new ArgumentNullException(nameof(user));

            if (Status == MeetingStatus.Cancelled)
                throw new InvalidOperationException("不能向已取消的会议添加参与者");

            if (!user.IsActive)
                throw new InvalidOperationException("不能添加非活跃用户为参会者");

            if (Participants.Contains(user))
                return;

            Participants.Add(user);

            if (!user.Meetings.Contains(this))
                user.Meetings.Add(this);

            if (!ParticipantIds.Contains(user.Id))
                ParticipantIds.Add(user.Id);

            UpdatedDate = DateTime.UtcNow;
        }

        public void UpdateDetails(string title, string description)
        {
            if (Status == MeetingStatus.Cancelled)
                throw new InvalidOperationException("不能更新已取消的会议");

            if (string.IsNullOrWhiteSpace(title))
                throw new ArgumentException("会议标题不能为空", nameof(title));

            Title = title;
            Description = description;
            UpdatedDate = DateTime.UtcNow;
        }

        public bool IsOrganizer(Guid userId)
        {
            return OrganizerId == userId;
        }

        public bool IsParticipant(Guid userId)
        {
            return ParticipantIds.Contains(userId);
        }
    }
}
